/* QAD_FormulaCostReport.p - Bill of Materials Cost Report                    */
/* Copyright 1986-2011 QAD Inc., Santa Barbara, CA, USA.                      */
/* All rights reserved worldwide.  This is an unpublished work.               */
/* $Id:: QAD_FormulaCostReport.p 10771 2011-10-13 06:56:28Z jxx            $: */
/*                                                                            */
/* Report matches legacy bmpsrp01.p for use by QAD Reporting Framework.       */
/*                                                                            */

{mfsubdirs.i}
{{&US_BBI}mfdeclre.i}
{{&US_BBI}gplabel.i}
{{&US_WO}woconsdf.i}
{{&US_PX}pxpgmmgr.i}
{{&US_PX}pxphdef.i ppitxr}

{com/qad/shell/report/dsReportRequest.i}
{com/qad/shell/report/ReportConstants.i}

/*============================================================================*/
/* ****************************  TEMP TABLES  ******************************* */
/*============================================================================*/

/* TEMP-TABLE DEFINITION BLOCK */
define temp-table ttMain no-undo
   field unique_id as integer
.

define temp-table tt_ps_mstr no-undo like ps_mstr
   field lvl                  as   character
   field um                   like pt_mstr.pt_um
   field batch_qty            like bom_mstr.bom_batch
   field batch_um             like bom_mstr.bom_batch_um
   field display_batch        like mfc_ctrl.mfc_logical
   field msg_desc             like msg_mstr.msg_desc
   field id_group_by_parent   as   integer
   field unique_id            as   integer
   field ref_unique_id        like ttMain.unique_id
   index idx unique_id
.

define temp-table ttDescription no-undo
   field description          as   character
   field ref_unique_id        as   integer
   index idx ref_unique_id
.

define temp-table ttCategoryCost no-undo
   field level_label       as character
   field mtl               like sct_det.sct_mtl_tl
   field lbr               like sct_det.sct_lbr_tl
   field bdn               like sct_det.sct_bdn_tl
   field ovh               like sct_det.sct_ovh_tl
   field sub               like sct_det.sct_sub_tl
   field tot               like sct_det.sct_cst_tot
   field ref_unique_id     as integer
   index idx ref_unique_id
.

define temp-table tt_spt_det no-undo like spt_det
   field category       as character
   field spt_tot        like sct_det.sct_cst_tot
   field spt_xtd        like sct_det.sct_cst_tot
   field ref_unique_id  as integer
   index idx ref_unique_id
.

define temp-table ttReportOptions no-undo
   field newpage      like mfc_ctrl.mfc_logical
   field catelm       like mfc_ctrl.mfc_logical
   field formula_only like mfc_ctrl.mfc_logical
.

define temp-table ttReportConditions no-undo
   field part      like pt_mstr.pt_part
   field altpart   like ptal_mstr.ptal_alt_part
   field numlevels as   integer
   field eff_date  as   date
   field site      like si_mstr.si_site
   field csset     like sct_det.sct_sim
.

define dataset dsReportResults for ttMain,tt_ps_mstr,ttDescription,
               ttCategoryCost, tt_spt_det, ttReportOptions, ttReportConditions.

/*============================================================================*/
/* *****************************  MAIN BLOCK  ******************************* */
/*============================================================================*/
define input parameter runReport    as logical no-undo.
define input parameter reportHandle as handle  no-undo.
define input parameter dataset      for dsReportRequest.
define output parameter dataset-handle phReportResults.

{com/qad/shell/report/reporting.i}
{com/qad/shell/report/reports/QAD_HelperFunctions.i}

define variable vhDS as handle no-undo.
define workfile pswkfl no-undo
   field psrecid     as recid
   field pscode      like ps_ps_code
   field psstart     like ps_start
   field psqtype     like ps_qty_type
   field qty_per     like ps_qty_per
   field qty_per_b   like ps_qty_per_b
   field net_qty     like ps_qty_per
.

empty temp-table ttMain             no-error.
empty temp-table tt_ps_mstr         no-error.
empty temp-table ttDescription      no-error.
empty temp-table ttCategoryCost     no-error.
empty temp-table tt_spt_det         no-error.
empty temp-table ttReportOptions    no-error.
empty temp-table ttReportConditions no-error.

for first ttReportRequest no-lock:

   vhDS = dataset dsReportResults:handle.
   run FillMetaData in reportHandle(
      vhDS, "QAD_FormulaCostReport.meta.xml").

   run SetReportMetaData (input reportHandle).

   if runReport then do:
      run RunReport
         (output dataset-handle phReportResults).
   end.

end.

PROCEDURE SetReportMetaData:

   define input parameter  ipReportHandle as handle.

   run SetFieldMetaParameter in ipReportHandle("ttReportOptions",
         "catelm", "DataFormat",getLabel("ELEMENT/CATEGORY")).

   run SetFieldMetaParameter in ipReportHandle ("ttReportOptions",
      "newpage", "DataFormat", getLabel("YES/NO")).

   run SetFieldMetaParameter in ipReportHandle ("ttReportOptions",
      "formula_only", "DataFormat", getLabel("YES/NO")).

   run SetFieldMetaParameter in ipReportHandle("ttReportConditions",
         "site", "DefaultValue", global_site).

   for first si_mstr no-lock where si_mstr.si_domain = global_domain
      and si_site = global_site:
   end.
   if available si_mstr
   then do:
      run SetFieldMetaParameter in ipReportHandle("ttReportConditions",
         "csset", "DefaultValue", si_cur_set).
   end.

END PROCEDURE. /* PROCEDURE ModifyMetaData */


/* DATA RETRIEVING LOGIC BLOCK */
PROCEDURE RunReport:

   define output parameter dataset-handle phReportResults.

   /* RETRIEVE THE DATA FROM DATABASE */
   define variable catelm        like mfc_ctrl.mfc_logical no-undo.
   define variable site          like si_mstr.si_site no-undo.
   define variable csset         like sct_det.sct_sim no-undo.
   
   assign
      catelm = IsTrueValue("ttReportOptions", "catelm", false)
      site   = GetFilterValue("ttReportConditions", "site", global_site)
      csset  = GetFilterValue("ttReportConditions", "csset", "")
   .

   /*Validate user-input site*/
   for first si_mstr where si_mstr.si_domain = global_domain
                     and   si_site           = site no-lock:
   end.
   if not available si_mstr
   then do:
      /* SITE DOES NOT EXIST */
      {{&US_BBI}pxmsg.i &MSGNUM=708 &ERRORLEVEL=3}
      return.
   end. /* IF NOT available si_mstr */
   if si_db <> global_db
   then do:
      /* SITE IS NOT ASSIGNED TO THIS DOMAIN */
      {{&US_BBI}pxmsg.i &MSGNUM=6251 &ERRORLEVEL=3}
      return.
   end. /* IF si_db <> global_db */

   /*Validate user-input costset*/
   if csset = ""
   then do:
      /* BLANK NOT ALLOWED */
      {{&US_BBI}pxmsg.i &MSGNUM=40 &ERRORLEVEL=3}
      return.
   end. /* IF csset = "" */

   for first cs_mstr where cs_mstr.cs_domain = global_domain
               and cs_set = csset no-lock:
   end.
   if not available cs_mstr
   then do:
      /* COST SET DOES NOT EXIST */
      {{&US_BBI}pxmsg.i &MSGNUM=5407 &ERRORLEVEL=3}
      return.
   end. /* IF NOT AVAILABLE cs_mstr */

   create ttReportOptions. /*used for ui main report*/

   if catelm
   then do:
      run CalculateProductStructureCostByElement(site, costset).
   end. /*By Element end*/

   else do:
      
   end. /*By Category end*/
   global_site = site.

   delete object hMainQuery.
   phReportResults = dataset dsReportResults:handle.

END PROCEDURE.

PROCEDURE AddDescriptions:

   /* Add descriptions of component */
   define input-output parameter des_count  as integer no-undo.
   define input parameter count_comp as integer no-undo.
   define input parameter description as character extent 10 no-undo.

   define variable i as integer no-undo.

   if count_comp = 0 /* no descriptions */
   then do:
      /* clear the description */
      des_count = 0.
      do i = 1 to 10:
         description[i] = " ".
      end.
   end. /*if count_comp =0*/
   else do:
      /* has descriptions */
      if des_count <> 0
      then do:
         do i =1 to des_count:
            create ttDescription.
            ttDescription.description = description[i].
            ttDescription.ref_unique_id = count_comp.
         end.
         des_count = 0. /* clear description */
      end.
   end. /* else do */

END PROCEDURE. /* PROCEDURE CreateDescription */


PROCEDURE CalculateProductStructureCostByElement:

   define input parameter site   like si_mstr.si_site no-undo.
   define input parameter csset  like sct_det.sct_sim no-undo.
   define variable queryString   as character no-undo.
   define variable hMainQuery    as handle    no-undo.
   define query    MainQuery     for pt_mstr,ptal_mstr.
   define variable eff_date      as date no-undo.
   define variable numlevels     as integer no-undo.
   define variable formula_only  like mfc_ctrl.mfc_logical no-undo.
   define variable count_comp    as integer initial 0 no-undo.
   define variable parent_id     as integer initial 0 no-undo.
   define variable first_record  as logical initial true no-undo.
   define variable usr_val       as character extent 5 no-undo.
   define variable usr_elm       like sc_mstr.sc_element extent 5 no-undo.
   define variable l_gl_std      like mfc_ctrl.mfc_logical no-undo.
   define variable comp          like ps_mstr.ps_comp no-undo.
   define variable bom_code      like pt_mstr.pt_bom_code no-undo.
   define variable level         as integer no-undo.
   define variable maxlevel      as integer no-undo.
   define variable yield_pct     like pt_mstr.pt_yield no-undo.
   define variable batch_qty     like bom_mstr.bom_batch no-undo.
   define variable batch_um      like bom_mstr.bom_batch_um no-undo.
   define variable parent        like ps_mstr.ps_par no-undo.
   define variable um            like pt_mstr.pt_um no-undo.
   define variable phantom       like mfc_ctrl.mfc_logical no-undo.
   define variable iss_pol       like pt_mstr.pt_iss_pol no-undo.
   define variable lvl           as character no-undo.
   define variable dpart         like pt_mstr.pt_part no-undo.
   define variable l_linked      like mfc_ctrl.mfc_logical no-undo.
   define variable des           as character extent 10 no-undo.
   define variable des_temp      as character extent 10 no-undo.
   define variable des_temp_count as integer initial 0 no-undo.
   define variable par_qty       like ps_mstr.ps_qty_per no-undo.
   define variable spt_tot       like sct_det.sct_cst_tot no-undo.
   define variable spt_xtd       like sct_det.sct_cst_tot no-undo.
   define variable joint_code    like wo_mstr.wo_joint_type no-undo.
   define variable joint_type    like wo_mstr.wo_joint_type no-undo.
   define variable joint_label   like lngd_det.lngd_translation no-undo.
   define variable i             as integer no-undo.
   define variable j             as integer no-undo.
   define variable k             as integer no-undo.
   define variable record        as integer extent 100 no-undo.
   define variable scrp_pct      like ps_mstr.ps_scrp_pct no-undo.
   define variable dingbats      as character initial "temp!@#$" no-undo.
   define buffer   ptmstr        for pt_mstr.
   define buffer   pt_mstr1      for pt_mstr. 
      
   assign
      hMainQuery   = query MainQuery:handle
      formula_only = IsTrueValue("ttReportOptions", "formula_only", false)
      eff_date     = GetDateFilterValue("ttReportConditions", "eff_date", TODAY)
      numlevels    = Integer(GetFilterValue("ttReportConditions", "numlevels",""))
   .

   for each lngd_det no-lock where lngd_dataset = "sc_mstr"
      and lngd_key1  = ""
      and lngd_key2  = ""
      and lngd_key3  = ""
      and lngd_field = "sc_category"
      and lngd_lang  = global_user_lang:
      
      assign
         usr_val[integer(lngd_key4)] = lngd_translation.
         usr_elm[integer(lngd_key4)] = substring(lngd_translation,1,3).
   end. /* for each lngd_det */
   
   /* RECOGNIZE SITE LINKS FOR GL COST WHEN A GL STANDARD COST SET IS SPECIFIED */
   /* CHECK IF THE COST SET ENTERED IS OF TYPE GL AND STANDARD METHOD */
   for first cs_mstr no-lock where cs_mstr.cs_domain = global_domain
         and  cs_set = csset:
      if cs_type = "GL" and cs_method = "STD"
      then do:
         l_gl_std = true.
      end.
   end. /* FOR FIRST CS_MSTR */

   /*Main Query*/
   queryString = "for each pt_mstr where pt_mstr.pt_domain = "
               + quoter(global_domain).
   run AddAllConditions in reportHandle
      ("pt_mstr", input-output queryString).

   queryString = queryString + " , first ptal_mstr no-lock ".
   if not IsConditionEmpty("ttReportConditions", "altpart")
   then do:
   queryString = queryString + " where ptal_mstr.ptal_domain = "
                  + quoter(global_domain)
                  + " and ptal_mstr.ptal_part = pt_mstr.pt_part "
                  + " and ptal_mstr.ptal_active ".

   run AddAllConditions in reportHandle
      ( "ptal_mstr" , input-output queryString).
   end. /* if not IsConditionEmpty(...) */

   queryString = queryString + ":".

   hMainQuery:query-prepare(queryString).
   hMainQuery:query-open().
   hMainQuery:get-next().

   repeat while not hMainQuery:query-off-end:

      if first_record
      then do:
         create ttMain.
         assign
            ttMain.unique_id = 1.
            first_record     = false.
      end.

      for first ptal_mstr where ptal_mstr.ptal_domain = global_domain
         and ptal_part = pt_part
         and ptal_active no-lock:
      end.

      assign
         comp       = pt_mstr.pt_part
         maxlevel   = min(numlevels,99)
         yield_pct  = pt_mstr.pt_yield_pct
         level      = 1
         batch_qty  = 1.

      if pt_mstr.pt_bom_code <> ""
      then do:
         bom_code = pt_mstr.pt_bom_code.
      end.
      else do:
         bom_code = pt_mstr.pt_part.
      end.

      for first ptp_det no-lock  where ptp_det.ptp_domain = global_domain
            and ptp_part = pt_part
            and ptp_site = site:
      end.
      if available ptp_det
      then do:
         if ptp_bom_code <> ""
         then do:
            bom_code = ptp_bom_code.
         end.
         else do:
            bom_code = ptp_part.
         end.
         yield_pct = ptp_yld_pct.
      end.

      comp = bom_code.

      for first bom_mstr
         where bom_mstr.bom_domain = global_domain
            and bom_parent = bom_code
            and (formula_only = no or bom_formula)
      no-lock:
      end. /* FOR FIRST bom_mstr */

      if not available bom_mstr then do:
         hMainQuery:get-next().
         next.
      end.
      else do:
         for first ps_mstr no-lock use-index ps_parcomp
            where ps_mstr.ps_domain = global_domain
                  and  ps_par = comp:
         end.
         if not available ps_mstr
         then do:
            hMainQuery:get-next().
            next.
         end.

         parent = pt_part.
         
         /* CHECK IF THIS ITEM IS LINKED TO ANOTHER SITE FOR THE COST  */
         l_linked = false.
         if l_gl_std then
         for first in_mstr no-lock
            where in_mstr.in_domain = global_domain
            and in_part = pt_part and in_site = site:
            if in_gl_cost_site <> in_site
            then do:
               assign
                  l_linked = true
                  des[10]  = "GLCSS" + string(in_gl_cost_site).
            end.
         end. /* FOR FIRST IN_MSTR */
         
         if l_linked then do:
         /*Cost Simulation Total Detail Table*/
            for first sct_det where sct_det.sct_domain = global_domain
                  and  sct_sim = csset and sct_part = pt_part
                  and sct_site = in_gl_cost_site no-lock:
            end.
         end.
         else do:
            for first sct_det where sct_det.sct_domain = global_domain
                  and sct_sim = csset and sct_part = pt_part
                  and sct_site = site no-lock:
            end.
         end.

         do i = 1 to 9:
            des[i] = " ".
         end.

         des[1] = " " + pt_desc1.
         des[2] = " " + pt_desc2.

         if available sct_det and sct_cst_date <> ?
            then des[3] = " " + string(year(sct_cst_date))
                           + "-" + string(month(sct_cst_date),"99")
                           + "-" + string(day(sct_cst_date),"99").

         if scrp_pct <> 0 or yield_pct <> 100
         then do:
            assign
               des[4] = "SCRAP" + string(scrp_pct, ">>9.99") + "%"
               des[5] = "YIELD" + string(yield_pct) + "%".
         end.
         for first bom_mstr no-lock
            where bom_mstr.bom_domain = global_domain
            and bom_parent = pt_part:
         end.

         if available bom_mstr then do:
            batch_qty = bom_batch.
            batch_um  = bom_batch_um.
         end.
         par_qty = 1.

         /*create description for previous tt_ps_mstr*/
         run AddDescriptions(input-output des_temp_count,
               count_comp, des_temp).

         create tt_ps_mstr.
         buffer-copy ps_mstr to tt_ps_mstr no-error.
         assign
            parent_id                     = parent_id + 1
            count_comp                    = count_comp + 1
            tt_ps_mstr.lvl                = getTermLabel("PARENT",6)
            tt_ps_mstr.ps_comp            = parent
            tt_ps_mstr.unique_id          = count_comp
            tt_ps_mstr.ref_unique_id      = 1
            tt_ps_mstr.ps_qty_per         = ?
            tt_ps_mstr.ps_qty_type        = ?
            tt_ps_mstr.um                 = ?
            tt_ps_mstr.ps_ps_code         = ?
            tt_ps_mstr.id_group_by_parent = parent_id.


         for first ptal_mstr where ptal_mstr.ptal_domain = global_domain
            and ptal_part = pt_mstr.pt_part
            and ptal_active no-lock:
         end.
         if available ptal_mstr
         then do:
            des_temp_count = des_temp_count + 1.
            des_temp[des_temp_count] = "ALTNB" + ptal_alt_part.
         end.

         assign
            tt_ps_mstr.ps_qty_per  = ?
            tt_ps_mstr.ps_qty_type = "".
            
         if batch_qty <> 0 and batch_qty <> 1
         then do:
            des[7] = "BATCH" + string(batch_qty)
                     + " " + batch_um.
         end.

         if available ptp_det then do:
            joint_type = ptp_joint_type.
         end.
         else do:
            joint_type = pt_joint_type.
         end.
         if joint_type <> "" then do:
            /* Numeric ps_joint_type returns alpha code, label */
            {us/gp/gplngn2a.i &file     = ""wo_mstr""
               &field    = ""wo_joint_type""
               &code     = joint_type
               &mnemonic = joint_code
               &label    = joint_label}
            des[8] = " " + joint_label.
         end.

         do k = 1 to 7:
            do j = 1 to 7:
               if des[j] = " " then do:
                  do i = j to 8:
                     des[i] = des[i + 1].
                  end.
               end.
            end.
         end.

         if available sct_det then do:
            i = -1.
            for each spt_det no-lock
               where spt_det.spt_domain = global_domain
                  and spt_site = sct_site
                  and spt_sim  = sct_sim
                  and spt_part = sct_part
            break by spt_site by spt_sim by spt_part
            by spt_pct_ll by spt_cst_tl descending by spt_element:

               i = min(8, i + 1).

               spt_tot = spt_cst_tl + spt_cst_ll.
               spt_xtd = par_qty * (spt_cst_tl + spt_cst_ll).
               if(i >= 1) then do:
                  des_temp_count = des_temp_count + 1.
                  des_temp[des_temp_count] = des[i].
               end.

               create tt_spt_det.
               buffer-copy spt_det to tt_spt_det no-error.
               assign
                  tt_spt_det.category      =
                           usr_elm[integer(truncate(spt_det.spt_pct_ll,0))]
                  tt_spt_det.spt_tot       = spt_tot
                  tt_spt_det.spt_xtd       = spt_xtd
                  tt_spt_det.ref_unique_id = count_comp.
               if last-of(spt_det.spt_part) then do:
                  do j = i + 1 to 0:
                     if des[j] <> " " then do:
                        des_temp_count = des_temp_count + 1.
                        des_temp[des_temp_count] = des[j].
                     end.
                  end.
               end. /*last-of spt_part*/
            end. /*for each spt_det end*/
         end. /*if available sct_det end*/

         /* IF THIS PARENT IS LINKED DISPLAY THE GL COST SITE */
         if l_linked then do:
            des_temp_count = des_temp_count + 1.
            des_temp[des_temp_count] = des[10].
         end.

         /* IF THIS PARENT IS LINKED DISPLAY THE LINKED COST AND GO TO THE */
         /* NEXT ITEM, DO NOT DISPLAY ITS COMPONENTS COST.                 */
         if l_linked then do:
            hMainQuery:get-next().
            next.
         end.
         repeat:
            l_linked = false.

            if l_gl_std then
            for first in_mstr
               fields( in_domain in_site in_gl_cost_site)
               where in_mstr.in_domain = global_domain
                  and  in_part = comp and in_site = site no-lock:

               if in_gl_cost_site <> in_site then do:
                  l_linked = true.
               end.
            end. /* FOR FIRST IN_MSTR */

            if (not available ps_mstr) or (l_linked) then do:
               repeat:
                  level = level - 1.
                  if level < 1 then leave.
                  for first ps_mstr no-lock
                     where recid(ps_mstr) = record[level]:
                  end.
                  comp = ps_mstr.ps_par.
                  find next ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp no-lock no-error.
                  if available ps_mstr then do:
                     leave.
                  end.
               end.
            end. /*if not available ps_mstr*/
            if level < 1 then leave.

            if eff_date = ? or (eff_date <> ? and
               (ps_mstr.ps_start = ? or ps_mstr.ps_start <= eff_date)
               and (ps_mstr.ps_end = ? or eff_date <= ps_mstr.ps_end))
            then do:

               assign
                  um        = ""
                  iss_pol   = {&ISSUE-POLICY-NONE}
                  phantom   = no
                  dpart     = ps_mstr.ps_comp
                  bom_code  = ps_mstr.ps_comp
                  yield_pct = 100
                  batch_qty = 1.

               do i = 1 to 9:
                  des[i] = " ".
               end.

               for first ptmstr where ptmstr.pt_domain = global_domain
                     and ptmstr.pt_part = ps_mstr.ps_comp no-lock:
               end.
               if available ptmstr then do:
                  assign um    = ptmstr.pt_um
                     des[1]    = " " + ptmstr.pt_desc1
                     des[2]    = " " + ptmstr.pt_desc2
                     iss_pol   = ptmstr.pt_iss_pol
                     phantom   = ptmstr.pt_phantom
                     yield_pct = ptmstr.pt_yield_pct
                     bom_code  = if ptmstr.pt_bom_code <> ""
                     then ptmstr.pt_bom_code else ptmstr.pt_part.

                  for first ptp_det no-lock
                     where ptp_det.ptp_domain = global_domain
                        and ptp_part = ptmstr.pt_part
                        and ptp_site = site:
                  end.
                  if available ptp_det
                  then do:
                     assign
                        phantom = ptp_phantom
                        yield_pct = ptp_yld_pct.
                     if ptp_bom_code <> ""
                     then do:
                        bom_code = ptp_bom_code.
                     end.
                     else do:
                        bom_code = ptp_part.
                     end.
                     {{&US_PX}pxrun.i
                        &PROC  = 'getFieldDefault'
                        &PROGRAM = 'ppitxr.p'
                        &HANDLE = ph_ppitxr
                        &PARAM = "( input  ptmstr.pt_part,
                                    input  site,
                                    input ""pt_iss_pol"",
                                    output iss_pol)"
                        &NOAPPERROR = true
                        &CATCHERROR = true
                     }
                  end.
               end.

               for first bom_mstr no-lock
                  where bom_mstr.bom_domain = global_domain
                     and bom_parent = ps_mstr.ps_comp:
               end.
               if available bom_mstr then do:
                  batch_qty = bom_batch.
                  batch_um  = bom_batch_um.
                  if not available ptmstr then do:
                     des[1] = " " + bom_desc.
                     um     = bom_batch_um.
                  end.
               end.

               record[level] = recid(ps_mstr).
               lvl = "......".
               lvl = substring(lvl,1,min(level - 1,5)) + string(level).
               if length(lvl) > 6
                  then lvl = substring(lvl,length(lvl) - 5,6).

               for each pswkfl exclusive-lock:
                  delete pswkfl.
               end.

               create pswkfl.
               assign
                  psrecid   = recid(ps_mstr)
                  pscode    = ps_mstr.ps_ps_code
                  psstart   = ps_mstr.ps_start
                  psqtype   = ps_mstr.ps_qty_type
                  qty_per_b = qty_per_b + ps_mstr.ps_qty_per_b
                  net_qty   = ps_mstr.ps_qty_per *
                     (100 / (100 - ps_mstr.ps_scrp_pct))
                  qty_per   = ps_mstr.ps_qty_per
               .

               repeat:
                  find next ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp
                     and ps_mstr.ps_comp = dpart no-lock.
                  if not available ps_mstr then do:
                     leave.
                  end.
                  record[level] = recid(ps_mstr).
                  if eff_date = ? or (eff_date <> ? 
                     and (ps_mstr.ps_start = ? or ps_mstr.ps_start <= eff_date)
                     and (ps_mstr.ps_end = ? or eff_date <= ps_mstr.ps_end)) 
                  then do:
                     for first pswkfl where pscode = ps_mstr.ps_ps_code
                        and psstart = ps_mstr.ps_start
                        and psqtype = ps_mstr.ps_qty_type:
                     end.
                     if not available pswkfl then do:
                        create pswkfl.
                        assign
                           pscode  = ps_mstr.ps_ps_code
                           psstart = ps_mstr.ps_start
                           psqtype = ps_mstr.ps_qty_type.
                     end.
                     
                     assign
                        psrecid   = recid(ps_mstr)
                        qty_per_b = qty_per_b + ps_mstr.ps_qty_per_b
                        qty_per   = qty_per + ps_mstr.ps_qty_per
                        net_qty   = net_qty + ps_mstr.ps_qty_per *
                           (100 / (100 - ps_mstr.ps_scrp_pct)).
                  end. /* if eff_date = ? or ... */
               end. /* repeat */

               for each pswkfl:
                  for first ps_mstr where recid(ps_mstr) = psrecid
                     no-lock:
                  end.

                  if available ptmstr then do:

                     l_linked = false.

                     if l_gl_std then
                     for first in_mstr
                        fields( in_domain in_site in_gl_cost_site)
                        where in_mstr.in_domain = global_domain
                        and in_part = ptmstr.pt_part
                        and in_site = site no-lock:

                        if in_gl_cost_site <> in_site then
                        assign
                           l_linked = true
                           des[10]  = "GLCSS"+ string(in_gl_cost_site).

                     end. /* FOR FIRST IN_MSTR */

                     if l_linked then do:
                        for first sct_det
                           where sct_det.sct_domain = global_domain
                           and sct_sim = csset
                           and sct_part = ptmstr.pt_part
                           and sct_site = in_gl_cost_site no-lock:
                        end.
                     end.
                     else do:
                        for first sct_det
                           where sct_det.sct_domain = global_domain
                           and sct_sim = csset
                           and sct_part = ptmstr.pt_part
                           and sct_site =  site no-lock:
                        end.
                     end.
                  end. /*if available ptmstr*/
                  else do: /*create a temporary 0.00 record*/
                     /*It is used in programs where the cost record
                       retrieval should be done literally.*/
                     for first sct_det exclusive-lock
                        where sct_det.sct_domain = global_domain
                        and  sct_sim = csset
                        and sct_part = dingbats
                        and sct_site = site:
                     end.

                     if not available sct_det then do:
                        create sct_det.
                        sct_det.sct_domain = global_domain.
                        assign
                           sct_sim       = csset
                           sct_part      = dingbats
                           sct_site      = site
                           sct_cst_date  = today
                           recno         = recid(sct_det).
                     end.

                     for each lngd_det no-lock
                        where lngd_dataset = "sc_mstr"
                        and lngd_key1 = ""
                        and lngd_key2 = ""
                        and lngd_key3 = ""
                        and lngd_field = "sc_category"
                        and lngd_lang = global_user_lang
                        and lookup(lngd_key4, "1,2,3,4,5") <> 0:
                        for first spt_det
                           where spt_det.spt_domain = global_domain
                           and spt_det.spt_site = sct_site
                           and spt_det.spt_sim = sct_sim
                           and spt_det.spt_part = sct_part
                           and truncate(spt_det.spt_pct_ll,0)
                           = decimal(lngd_key4) no-lock:
                        end.

                        if not available spt_det then do:
                           create spt_det.
                           spt_det.spt_domain = global_domain.
                           assign
                              spt_det.spt_site   = sct_site
                              spt_det.spt_sim    = sct_sim
                              spt_det.spt_part   = sct_part
                              spt_det.spt_element
                                 = substring(lngd_translation,1,8)
                              spt_det.spt_pct_ll = decimal(lngd_key4)
                              recno = recid(spt_det).
                        end.
                     end.
                     /*gpsct08.i extend end */
                  end.

                  scrp_pct = 0.
                  if net_qty <> 0
                     then scrp_pct = 100 * (net_qty - qty_per) / net_qty.

                  if available sct_det and sct_cst_date <> ?
                     then des[3] = " " + string(year(sct_cst_date))
                           + "-" + string(month(sct_cst_date),"99")
                           + "-" + string(day(sct_cst_date),"99").
                  if scrp_pct     <> 0
                     or yield_pct <> 100
                  then
                     assign
                        des[4] = "SCRAP" + string(scrp_pct, ">>9.99") + "%"
                        des[5] = "YIELD" + string(yield_pct)      + "%".

                  if bom_code <> ps_mstr.ps_comp then do:
                     des[6] = "BOMCD" + bom_code.
                  end.

                  /*create description for previous tt_ps_mstr*/
                  run AddDescriptions(input-output des_temp_count,
                                       count_comp, des_temp).

                  create tt_ps_mstr.
                  buffer-copy ps_mstr to tt_ps_mstr no-error.
                  count_comp = count_comp + 1.
                  assign
                     tt_ps_mstr.lvl                = lvl
                     tt_ps_mstr.ps_qty_per         = qty_per
                     tt_ps_mstr.um                 = um
                     tt_ps_mstr.unique_id          = count_comp
                     tt_ps_mstr.ref_unique_id      = 1
                     tt_ps_mstr.id_group_by_parent = parent_id
                     tt_ps_mstr.ps_qty_per         = qty_per_b
                     tt_ps_mstr.ps_qty_type        = ps_mstr.ps_qty_type.

                  if batch_qty <> 0 and batch_qty <> 1
                  then do:
                     des[7] = "BATCH" + string(batch_qty) + " "
                              + batch_um.
                  end.

                  for first ptal_mstr
                     where ptal_mstr.ptal_domain = global_domain
                     and ptal_part = ps_mstr.ps_comp
                     and ptal_active no-lock:
                  end.
                  if available ptal_mstr
                  then do:
                     des_temp_count = des_temp_count + 1.
                     des_temp[des_temp_count] = "ALTNB" + ptal_alt_part.
                  end.

                  joint_type = "".
                  joint_label = "".
                  for first ptp_det no-lock
                     where ptp_det.ptp_domain = global_domain
                     and ptp_part = ps_mstr.ps_comp
                     and ptp_site = site:
                  end.
                  if available ptp_det then joint_type = ptp_joint_type.
                  else do:
                     for first pt_mstr1 no-lock
                        where pt_mstr1.pt_domain = global_domain
                        and pt_mstr1.pt_part = ps_mstr.ps_comp:
                     end.
                     if available pt_mstr1 then do:
                        joint_type = pt_mstr1.pt_joint_type.
                     end.
                  end.
                  if joint_type <> "" then do:
                     /* Numeric ps_joint_type returns alpha code, label*/
                     {us/gp/gplngn2a.i &file     = ""wo_mstr""
                        &field    = ""wo_joint_type""
                        &code     = joint_type
                        &mnemonic = joint_code
                        &label    = joint_label}
                     des[8] = " " + joint_label.
                  end.

                  do j = 1 to 7:
                     do i = j + 1 to 8:
                        if des[i] = des[j] then do:
                           des[i] = " ".
                        end.
                     end.
                  end.

                  do k = 1 to 7:
                     do j = 1 to 7:
                        if des[j] = " " then do:
                           do i = j to 8:
                              des[i] = des[i + 1].
                           end.
                        end.
                     end.
                  end.

                  if available sct_det then do:
                     i = -1.
                     for each spt_det no-lock
                        where spt_det.spt_domain = global_domain
                        and spt_det.spt_site = sct_site
                        and spt_det.spt_sim  = sct_sim
                        and spt_det.spt_part = sct_part
                     break by spt_det.spt_site by spt_det.spt_sim
                     by spt_det.spt_part
                     by spt_det.spt_pct_ll
                     by spt_det.spt_cst_tl descending
                     by spt_det.spt_element:

                        i = min(8, i + 1).

                        spt_tot = spt_det.spt_cst_tl
                                        + spt_det.spt_cst_ll.
                        spt_xtd = qty_per * (spt_det.spt_cst_tl
                                          + spt_det.spt_cst_ll)
                        * (100 / (100 - scrp_pct)).

                        if i >= 1
                        then do:
                           des_temp_count = des_temp_count + 1.
                           des_temp[des_temp_count] = des[i].
                        end.
                        create tt_spt_det.
                        buffer-copy spt_det to tt_spt_det no-error.
                        assign
                           tt_spt_det.category      =
                        usr_elm[integer(truncate(spt_det.spt_pct_ll,0))]
                           tt_spt_det.spt_tot       = spt_tot
                           tt_spt_det.spt_xtd       = spt_xtd
                           tt_spt_det.ref_unique_id = count_comp.

                        if last-of(spt_det.spt_part) then do:
                           do j = i + 1 to 9:
                              if fill(" ",2) + des[j] <> " " then do:
                                 des_temp_count = des_temp_count + 1.
                                 des_temp[des_temp_count] = des[j].
                              end.
                           end.
                        end. /* IF LAST-OF(spt_part)... */
                     end. /* FOR EACH spt_det */
                  end. /* IF AVAILABLE spt_det */

                  /* IF THIS PARENT IS LINKED DISPLAY THE GL COST SITE */
                  if l_linked then do:
                     des_temp_count = des_temp_count + 1.
                     des_temp[des_temp_count] = des[10].
                  end.
               end. /*for each pswkfl*/

               for first ps_mstr where recid(ps_mstr) = record[level]
                  no-lock:
               end.

               if level < maxlevel or maxlevel = 0 then do:
                  comp = bom_code.
                  level = level + 1.
                  for first ps_mstr use-index ps_parcomp
                      where ps_mstr.ps_domain = global_domain
                      and ps_mstr.ps_par = comp no-lock:
                  end.
               end.
               else do:
                  find next ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp no-lock no-error.
               end.

               if available sct_det and sct_part = dingbats then do:
                  for each spt_det exclusive-lock
                     where spt_det.spt_domain = global_domain
                     and pt_mstr.pt_site = sct_site
                     and spt_det.spt_sim = sct_sim
                     and spt_det.spt_part = sct_part:
                     delete spt_det.
                  end.
                  delete sct_det.
               end.
            end. /*if eff_date = ? line 585*/
            else do:
               find next ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp no-lock no-error.
            end.
         end. /* Repeat end */
      end. /* IF AVAILABLE bom_mstr */

      hMainQuery:get-next().
   end. /* REPEAT QUERY */

   hMainQuery:query-close().

   /*create description for last tt_ps_mstr*/
   run AddDescriptions(input-output des_temp_count, count_comp, des_temp).

END PROCEDURE. /* PROCEDURE CalculateProductStructureCostByElement */




PROCEDURE CalculateProductStructureCostByCategory:
   
   define input parameter site   like si_mstr.si_site no-undo.
   define input parameter csset  like sct_det.sct_sim no-undo.
   define variable queryString   as character no-undo.
   define variable hMainQuery    as handle    no-undo.
   define query    MainQuery     for pt_mstr,ptal_mstr.
   define variable eff_date      as date no-undo.
   define variable numlevels     as integer no-undo.
   define variable formula_only  like mfc_ctrl.mfc_logical no-undo.
   define variable count_comp    as integer initial 0 no-undo.
   define variable parent_id     as integer initial 0 no-undo.
   define variable first_record  as logical initial true no-undo.

   define variable usr_val       as character extent 5 no-undo.
   define variable usr_elm       like sc_mstr.sc_element extent 5 no-undo.
   define variable l_gl_std      like mfc_ctrl.mfc_logical no-undo.
   define variable comp          like ps_mstr.ps_comp no-undo.
   define variable bom_code      like pt_mstr.pt_bom_code no-undo.
   define variable level         as integer no-undo.
   define variable maxlevel      as integer no-undo.
   define variable yield_pct     like pt_mstr.pt_yield no-undo.
   define variable batch_qty     like bom_mstr.bom_batch no-undo.
   define variable batch_um      like bom_mstr.bom_batch_um no-undo.
   define variable parent        like ps_mstr.ps_par no-undo.
   define variable um            like pt_mstr.pt_um no-undo.
   define variable phantom       like mfc_ctrl.mfc_logical no-undo.
   define variable iss_pol       like pt_mstr.pt_iss_pol no-undo.
   define variable lvl           as character no-undo.
   define variable dpart         like pt_mstr.pt_part no-undo.
   define variable l_linked      like mfc_ctrl.mfc_logical no-undo.
   define variable des           as character extent 10 no-undo.
   define variable des_temp      as character extent 10 no-undo.
   define variable des_temp_count as integer initial 0 no-undo.
   define variable par_qty       like ps_mstr.ps_qty_per no-undo.
   define variable spt_tot       like sct_det.sct_cst_tot no-undo.
   define variable spt_xtd       like sct_det.sct_cst_tot no-undo.
   define variable joint_code    like wo_mstr.wo_joint_type no-undo.
   define variable joint_type    like wo_mstr.wo_joint_type no-undo.
   define variable joint_label   like lngd_det.lngd_translation no-undo.
   define variable i             as integer no-undo.
   define variable j             as integer no-undo.
   define variable k             as integer no-undo.
   define variable m             as integer no-undo.
   define variable record        as integer extent 100 no-undo.
   define variable scrp_pct      like ps_mstr.ps_scrp_pct no-undo.
   define variable dingbats      as character initial "temp!@#$" no-undo.
   define buffer   ptmstr        for pt_mstr.
   define buffer   pt_mstr1      for pt_mstr.

   define variable mtl_tl        like sct_det.sct_mtl_tl no-undo.
   define variable lbr_tl        like sct_det.sct_lbr_tl no-undo.
   define variable bdn_tl        like sct_det.sct_bdn_tl no-undo.
   define variable ovh_tl        like sct_det.sct_ovh_tl no-undo.
   define variable sub_tl        like sct_det.sct_sub_tl no-undo.
   define variable total_tl      like sct_det.sct_cst_tot no-undo.
   define variable mtl_tot       like mtl_tl no-undo.
   define variable lbr_tot       like lbr_tl no-undo.
   define variable bdn_tot       like bdn_tl no-undo.
   define variable ovh_tot       like ovh_tl no-undo.
   define variable sub_tot       like sub_tl no-undo.
   define variable total_ll      like total_tl no-undo.
   define variable mtl_ext       like mtl_tl no-undo.
   define variable lbr_ext       like sub_tl no-undo.
   define variable bdn_ext       like bdn_tl no-undo.
   define variable ovh_ext       like ovh_tl no-undo.
   define variable sub_ext       like sub_tl no-undo.
   define variable total_ext     like total_tl no-undo.
 
   /* RECOGNIZE SITE LINKS FOR GL COST WHEN A GL STANDARD
      COST SET IS SPECIFIED */
   /* CHECK IF THE COST SET ENTERED IS OF TYPE GL AND STANDARD METHOD */
   for first cs_mstr no-lock
      where cs_mstr.cs_domain = global_domain
      and  cs_set = csset:
         if cs_type = "GL" and cs_method = "STD"
         then do:
            l_gl_std = true.
         end.
   end. /* FOR FIRST CS_MSTR */

   /*Main Query*/
   queryString = "for each pt_mstr where pt_mstr.pt_domain = "
               + quoter(global_domain).
   run AddAllConditions in reportHandle
      ("pt_mstr", input-output queryString).

   queryString = queryString + " , first ptal_mstr no-lock ".
   if not IsConditionEmpty("ttReportConditions", "altpart")
   then do:
   queryString = queryString + " where ptal_mstr.ptal_domain = "
                  + quoter(global_domain)
                  + " and ptal_mstr.ptal_part = pt_mstr.pt_part "
                  + " and ptal_mstr.ptal_active ".

   run AddAllConditions in reportHandle
      ( "ptal_mstr" , input-output queryString ).
   end. /* if not IsConditionEmpty(...) */

   queryString = queryString + ":".

   hMainQuery:query-prepare(queryString).
   hMainQuery:query-open().
   hMainQuery:get-next().

   repeat while not hMainQuery:query-off-end:

      if first_record
      then do:
         create ttMain.
         ttMain.unique_id = 1.
         first_record = false.
      end.

      for first ptal_mstr where ptal_mstr.ptal_domain = global_domain
         and ptal_part = pt_mstr.pt_part
         and ptal_active no-lock:
      end.

      assign
         comp        = pt_part
         bom_code    = if pt_bom_code <> "" then pt_bom_code else pt_part
         maxlevel    = min(numlevels,99)
         yield_pct   = pt_yield_pct
         scrp_pct    = 0
         level       = 1.

      for first ptp_det no-lock
         where ptp_det.ptp_domain = global_domain
         and  ptp_part = pt_part
         and ptp_site = site:
      end.

      if available ptp_det
      then do:
         if ptp_bom_code <> ""
         then do:
            bom_code = ptp_bom_code.
         end.
         else do:
            bom_code = ptp_part.
         end.
         yield_pct = ptp_yld_pct.
      end.

      comp = bom_code.

      for first bom_mstr
         where bom_mstr.bom_domain = global_domain
         and bom_parent = bom_code
         and (formula_only = no or bom_formula) no-lock:
      end. /* FOR FIRST bom_mstr */

      if not available bom_mstr then do:
         hMainQuery:get-next().
         next.
      end.
      else do:

         for first ps_mstr no-lock
            use-index ps_parcomp
            where ps_mstr.ps_domain = global_domain
            and  ps_mstr.ps_par = comp:
         end.

         if not available ps_mstr
         then do:
            hMainQuery:get-next().
            next.
         end.

         parent = pt_part.

         /* CHECK IF THIS ITEM IS LINKED TO ANOTHER SITE FOR GL COST  */
         l_linked = false.
         if l_gl_std then
         for first in_mstr no-lock
            where in_mstr.in_domain = global_domain
            and in_part = pt_part
            and in_site = site:

            if in_gl_cost_site <> in_site
            then do:
               assign
                  l_linked = true
                  des[8]   = "GLCSS" + string(in_gl_cost_site).
            end.
         end. /* FOR FIRST IN_MSTR */

         if l_linked
         then do:
            for first sct_det
               where sct_det.sct_domain = global_domain
               and  sct_sim = csset
               and sct_part = pt_part
               and sct_site = in_gl_cost_site no-lock:
            end.
         end.
         else do:
            for first sct_det
               where sct_det.sct_domain = global_domain
               and  sct_sim = csset
               and sct_part = pt_part
               and sct_site = site no-lock:
            end.
         end.

         /* START DISPLAY */
         if available sct_det   then do:
         assign
            total_tl = sct_mtl_tl + sct_lbr_tl
                     + sct_bdn_tl + sct_sub_tl + sct_ovh_tl
            total_ll = sct_mtl_ll + sct_lbr_ll
                     + sct_bdn_ll + sct_sub_ll + sct_ovh_ll
            mtl_tot  = sct_mtl_tl + sct_mtl_ll
            lbr_tot  = sct_lbr_tl + sct_lbr_ll
            bdn_tot  = sct_bdn_tl + sct_bdn_ll
            ovh_tot  = sct_ovh_tl + sct_ovh_ll
            sub_tot  = sct_sub_tl + sct_sub_ll
            des[2]   = " " + pt_desc2
            des[3]   = " ".
         end.
         else do:
            assign
               total_tl = 0
               total_ll = 0
               mtl_tot  = 0
               lbr_tot  = 0
               bdn_tot  = 0
               ovh_tot  = 0
               sub_tot  = 0
               des[2]   = " " + pt_desc2
               des[3]   = " ".
         end.
         if available sct_det and sct_cst_date <> ?
         then do:
            if des[2] = " " then do:
               des[2] = " " + string(year(sct_cst_date))
                           + "-" + string(month(sct_cst_date),"99")
                           + "-" + string(day(sct_cst_date),"99").
            end.
            else do:
               des[3] = " " + string(year(sct_cst_date))
                           + "-" + string(month(sct_cst_date),"99")
                           + "-" + string(day(sct_cst_date),"99").
            end.
         end.

         assign
            des[4] = " "
            des[5] = " ".

         if scrp_pct <> 0 and yield_pct = 100
         then do:
            des[4] = "SCRAP" + string(scrp_pct, ">>9.99") + "%".
         end.

         if scrp_pct = 0 and yield_pct <> 100
         then do:
            des[4] = des[4] + "YIELD" + string(yield_pct) + "%".
         end.

         if scrp_pct <> 0 and yield_pct <> 100
         then do:
            assign
               des[4] = "SCRAP" + string(scrp_pct, ">>9.99") + "%"
               des[5] = "YIELD" + string(yield_pct) + "%".
         end.

         if des[3] = " "
         then do:
            assign
               des[3] = des[4]
               des[4] = des[5]
               des[5] = " ".
         end.

         for first bom_mstr no-lock
            where bom_mstr.bom_domain = global_domain
            and bom_parent = pt_part:
         end.

         if available bom_mstr
         then do:
            assign
               batch_qty = bom_batch
               batch_um  = bom_batch_um.
         end.

         /*create description for previous tt_ps_mstr*/
         run AddDescriptions(input-output des_temp_count,
                             count_comp, des_temp).

         create tt_ps_mstr.
         buffer-copy ps_mstr to tt_ps_mstr no-error.
         count_comp = count_comp + 1.
         parent_id = parent_id + 1.
         assign
            tt_ps_mstr.lvl                = getTermLabel("PARENT",6)
            tt_ps_mstr.ps_comp            = parent
            tt_ps_mstr.unique_id          = count_comp
            tt_ps_mstr.ref_unique_id      = 1
            tt_ps_mstr.ps_qty_per         = ?
            tt_ps_mstr.ps_qty_type        = ?
            tt_ps_mstr.um                 = ?
            tt_ps_mstr.ps_ps_code         = ?
            tt_ps_mstr.id_group_by_parent = parent_id.

         for first ptal_mstr
            where ptal_mstr.ptal_domain = global_domain
            and ptal_part = pt_mstr.pt_part
            and ptal_active no-lock:
         end.
         if available ptal_mstr
         then do:
            des_temp_count = des_temp_count + 1.
            des_temp[des_temp_count] = "ALTNB" + ptal_alt_part.
         end.

         if batch_qty <> 1
         then do:
            tt_ps_mstr.batch_qty = batch_qty.
            tt_ps_mstr.batch_um = batch_um.
            tt_ps_mstr.display_batch = true.
         end.

         des_temp_count = des_temp_count + 1.
         des_temp[des_temp_count] = " " + pt_desc1.
         create ttCategoryCost.
         assign
            ttCategoryCost.level_label    = getTermLabelRt("THIS_LEVEL",12)
            ttCategoryCost.tot            = total_tl
            ttCategoryCost.ref_unique_id  = count_comp.

         if available sct_det
         then do:
            assign
               ttCategoryCost.mtl = sct_det.sct_mtl_tl
               ttCategoryCost.lbr = sct_det.sct_lbr_tl
               ttCategoryCost.bdn = sct_det.sct_bdn_tl
               ttCategoryCost.ovh = sct_det.sct_ovh_tl
               ttCategoryCost.sub = sct_det.sct_sub_tl.
         end.
         else do:
            assign
               ttCategoryCost.mtl = 0
               ttCategoryCost.lbr = 0
               ttCategoryCost.bdn = 0
               ttCategoryCost.ovh = 0
               ttCategoryCost.sub = 0.
         end.

         des_temp_count = des_temp_count + 1.
         des_temp[des_temp_count] = des[2].
         create ttCategoryCost.
         assign
            ttCategoryCost.level_label    = getTermLabelRt("LOWER_LEVEL",12)
            ttCategoryCost.tot            = total_ll
            ttCategoryCost.ref_unique_id  = count_comp.
         if available sct_det
         then do:
            assign
               ttCategoryCost.mtl = sct_mtl_ll
               ttCategoryCost.lbr = sct_lbr_ll
               ttCategoryCost.bdn = sct_bdn_ll
               ttCategoryCost.ovh = sct_ovh_ll
               ttCategoryCost.sub = sct_sub_ll.
         end.
         else do:
            assign
               ttCategoryCost.mtl = 0
               ttCategoryCost.lbr = 0
               ttCategoryCost.bdn = 0
               ttCategoryCost.ovh = 0
               ttCategoryCost.sub = 0.
         end.

         des_temp_count = des_temp_count + 1.
         des_temp[des_temp_count] = des[3].
         create ttCategoryCost.
         assign
            ttCategoryCost.level_label    = getTermLabelRt("UNIT_TOTAL",12)
            ttCategoryCost.mtl            = mtl_tot
            ttCategoryCost.lbr            = lbr_tot
            ttCategoryCost.bdn            = bdn_tot
            ttCategoryCost.ovh            = ovh_tot
            ttCategoryCost.sub            = sub_tot
            ttCategoryCost.ref_unique_id  = count_comp.

         if available sct_det
         then do:
            ttCategoryCost.tot = sct_cst_tot.
         end.
         else do:
            ttCategoryCost.tot = 0.
         end.
         if des[4] <> " "
         then do:
            des_temp_count = des_temp_count + 1.
            des_temp[des_temp_count] = des[4].
         end.
         if des[5] <> " "
         then do:
            des_temp_count = des_temp_count + 1.
            des_temp[des_temp_count] = des[5].
         end.

         if bom_code <> parent
         then do:
            if des[3] <> " "
            then do:
               des_temp_count = des_temp_count + 1.
               des_temp[des_temp_count] = "BOMCD" + bom_code.
            end.
            else do:
               des_temp[3] = "BOMCD" + bom_code.
            end.
         end.

         joint_label = "".

         if available ptp_det
         then do:
            joint_type = ptp_joint_type.
         end.

         else do:
            joint_type = pt_joint_type.
         end.

         if joint_type <> ""
         then do:
            /* Numeric ps_joint_type returns alpha code, label */
            {{&us_gp}gplngn2a.i &file     = ""wo_mstr""
               &field    = ""wo_joint_type""
               &code     = joint_type
               &mnemonic = joint_code
               &label    = joint_label}
            if bom_code <> parent or des[3] <> " "
            then do:
               des_temp_count = des_temp_count + 1.
               des_temp[des_temp_count] = " " + joint_label.
            end.
            else do:
               des_temp[3] = " " + joint_label.
            end.
         end. /* end of if joint_type*/

         /* IF THIS PARENT IS LINKED DISPLAY THE GL COST SITE */
         if l_linked
         then do:
            des_temp_count = des_temp_count + 1.
            des_temp[des_temp_count] = des[8].
         end.

         /* IF THIS PARENT IS LINKED DISPLAY THE LINKED COST AND GO TO THE */
         /* NEXT ITEM, DO NOT DISPLAY ITS COMPONENTS COST.                 */
         if l_linked
         then do:
            hMainQuery:get-next().
            next.
         end.

         repeat:

            l_linked = false.

            if l_gl_std
            then do:
               for first in_mstr
               fields( in_domain in_site in_gl_cost_site)
                  where in_mstr.in_domain = global_domain
                  and in_part = comp
                  and in_site = site no-lock:

                  if in_gl_cost_site <> in_site
                  then do:
                     l_linked = true.
                  end.
               end. /* FOR FIRST IN_MSTR */
            end. /* end if l_gl_std*/

            if (not available ps_mstr) or (l_linked)
            then do:
               repeat:
                  level = level - 1.
                  if level < 1 then leave.
                  for first ps_mstr
                     where recid(ps_mstr) = record[level] no-lock:
                  end.
                  comp = ps_mstr.ps_par.
                  find next ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp no-lock no-error.
                  if available ps_mstr
                  then do:
                     leave.
                  end.
               end.

            end. /*end  if not available or*/

            if level < 1 then leave.

            if eff_date = ? or (eff_date <> ? and
               (ps_mstr.ps_start = ? or ps_mstr.ps_start <= eff_date)
               and (ps_mstr.ps_end = ? or eff_date <= ps_mstr.ps_end))
            then do:
               assign
                  des[1]    = " " + getTermLabel("ITEM_NOT_IN_INVENTORY",24)
                  des[2]    = " "
                  des[3]    = " "
                  um        = ""
                  iss_pol   = {&ISSUE-POLICY-NONE}
                  phantom   = no
                  dpart     = ps_mstr.ps_comp
                  bom_code  = ps_mstr.ps_comp
                  batch_qty = 1
                  yield_pct = 100.

               for first ptmstr
                  where ptmstr.pt_domain = global_domain
                  and ptmstr.pt_part = ps_mstr.ps_comp no-lock:
               end.

               if available ptmstr
               then do:
                  assign
                     um        = ptmstr.pt_um
                     des[1]    = " " + ptmstr.pt_desc1
                     des[2]    = " " + ptmstr.pt_desc2
                     iss_pol   = ptmstr.pt_iss_pol
                     phantom   = ptmstr.pt_phantom
                     yield_pct = ptmstr.pt_yield_pct
                  .
                  if ptmstr.pt_bom_code <> ""
                  then do:
                     bom_code = ptmstr.pt_bom_code.
                  end.
                  else do:
                     bom_code = ptmstr.pt_part.
                  end.

                  for first ptp_det no-lock
                     where ptp_det.ptp_domain = global_domain
                     and ptp_part = ptmstr.pt_part
                     and ptp_site = site:
                  end.

                  if available ptp_det
                  then do:
                     assign
                        phantom   = ptp_phantom
                        yield_pct = ptp_yld_pct.
                     if ptp_bom_code <> ""
                     then do:
                        bom_code = ptp_bom_code.
                     end.
                     else do:
                        bom_code = ptp_part.
                     end.
                     {{&US_PX}pxrun.i
                        &PROC  = 'getFieldDefault'
                        &PROGRAM = 'ppitxr.p'
                        &HANDLE = ph_ppitxr
                        &PARAM = "( input  ptmstr.pt_part,
                                    input  site,
                                    input ""pt_iss_pol"",
                                    output iss_pol)"
                        &NOAPPERROR = true
                        &CATCHERROR = true
                     }
                  end.
               end. /* end  if available ptmstr*/

               for first bom_mstr no-lock
                  where bom_mstr.bom_domain = global_domain
                  and bom_parent = ps_mstr.ps_comp:
               end.

               if available bom_mstr
               then do:
                  assign
                     batch_qty = bom_batch
                     batch_um  = bom_batch_um.

                  if not available ptmstr
                  then do:
                     assign
                        des[1]   = " " + bom_desc
                        um       = bom_batch_um.
                  end.
               end. /*end if available bom_mstr*/

               assign
                  record[level]  = recid(ps_mstr)
                  lvl            = "......"
                  lvl            = substring(lvl,1,min(level - 1,5))
                                 + string(level).

               if length(lvl) > 6
               then do:
                  lvl = substring(lvl,length(lvl) - 5,6).
               end.

               for each pswkfl exclusive-lock:
                  delete pswkfl.
               end.

               create pswkfl.
               assign
                  psrecid   = recid(ps_mstr)
                  pscode    = ps_mstr.ps_ps_code
                  psstart   = ps_mstr.ps_start
                  psqtype   = ps_mstr.ps_qty_type
                  qty_per_b = qty_per_b + ps_mstr.ps_qty_per_b.

               if ps_mstr.ps_scrp_pct = 100
               then do:
                  net_qty = 0.
               end.

               else do:
                  net_qty = ps_mstr.ps_qty_per
                     * (100 / (100 - ps_mstr.ps_scrp_pct)).
               end.

               qty_per = ps_mstr.ps_qty_per.

               repeat:
                  find next ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp
                     and ps_mstr.ps_comp = dpart no-lock no-error.

                  if not available ps_mstr then leave.

                  record[level] = recid(ps_mstr).

                  if eff_date = ? or (eff_date <> ? and
                     (ps_mstr.ps_start = ? or ps_mstr.ps_start <= eff_date)
                     and (ps_mstr.ps_end = ? or eff_date <= ps_mstr.ps_end))
                  then do:
                     for first pswkfl where pscode = ps_mstr.ps_ps_code
                        and psstart = ps_mstr.ps_start
                        and psqtype = ps_mstr.ps_qty_type:
                     end.

                     if not available pswkfl
                     then do:
                        create pswkfl.
                        assign
                           pscode  = ps_mstr.ps_ps_code
                           psstart = ps_mstr.ps_start
                           psqtype = ps_mstr.ps_qty_type.
                     end.

                     assign
                        psrecid   = recid(ps_mstr)
                        qty_per_b = qty_per_b + ps_mstr.ps_qty_per_b
                        qty_per   = qty_per + ps_mstr.ps_qty_per.

                     if ps_mstr.ps_scrp_pct = 100
                     then do:
                        net_qty = 0.
                     end.
                     else do:
                        net_qty = net_qty + ps_mstr.ps_qty_per
                           * (100 / (100 - ps_mstr.ps_scrp_pct)).
                     end.
                  end. /* end if eff_date =? */
               end. /* repeat  end */

               for each pswkfl:
                  for first ps_mstr
                     where recid(ps_mstr) = psrecid no-lock:
                  end.

                  if available ptmstr
                  then do:
                     l_linked = false.

                     if l_gl_std then do:
                        for first in_mstr
                           fields(in_domain in_site in_gl_cost_site)
                           where in_mstr.in_domain = global_domain
                           and in_part = ptmstr.pt_part
                           and in_site = site no-lock:

                           if in_gl_cost_site <> in_site then
                              assign
                                l_linked = true
                                des[8]   = "GLCSS" + string(in_gl_cost_site).
                        end. /* FOR FIRST IN_MSTR */
                     end.
                     if l_linked
                     then do:
                        for first sct_det
                           where sct_det.sct_domain = global_domain
                           and sct_sim = csset
                           and sct_part = ptmstr.pt_part
                           and sct_site = in_gl_cost_site no-lock:
                        end.
                     end.
                     else do:
                        for first sct_det
                           where sct_det.sct_domain = global_domain
                           and sct_sim = csset
                           and sct_part = ptmstr.pt_part
                           and sct_site = site no-lock:
                        end.
                     end.
                  end. /* if available ptmstr*/
                  else do: /*create a temporary 0.00 record*/
                     /*It is used in programs where the cost record
                       retrieval should be done literally.*/
                     for first sct_det exclusive-lock
                        where sct_det.sct_domain = global_domain
                        and  sct_sim = csset
                        and sct_part = dingbats
                        and sct_site = site:
                     end.

                     if not available sct_det then do:
                        create sct_det.
                        sct_det.sct_domain = global_domain.
                        assign sct_sim       = csset
                               sct_part      = dingbats
                               sct_site      = site
                               sct_cst_date  = today
                               recno         = recid(sct_det).
                     end.

                     for each lngd_det no-lock
                        where lngd_dataset = "sc_mstr"
                        and lngd_key1 = ""
                        and lngd_key2 = ""
                        and lngd_key3 = ""
                        and lngd_field = "sc_category"
                        and lngd_lang = global_user_lang
                        and lookup(lngd_key4, "1,2,3,4,5") <> 0:
                        for first spt_det
                           where spt_det.spt_domain = global_domain
                           and spt_det.spt_site = sct_site
                           and spt_det.spt_sim = sct_sim
                           and spt_det.spt_part = sct_part
                           and truncate(spt_det.spt_pct_ll,0)
                           = decimal(lngd_key4) no-lock:
                        end.

                        if not available spt_det then do:
                           create spt_det. spt_det.spt_domain
                                    = global_domain.
                           assign
                              spt_det.spt_site   = sct_site
                              spt_det.spt_sim    = sct_sim
                              spt_det.spt_part   = sct_part
                              spt_det.spt_element
                                 = substring(lngd_translation,1,8)
                              spt_det.spt_pct_ll = decimal(lngd_key4)
                              recno = recid(spt_det).
                        end.
                     end. /*gpsct08.i extend end */
                  end.

                  if available sct_det
                  then do:
                     assign
                        total_tl = sct_mtl_tl + sct_lbr_tl + sct_bdn_tl
                        + sct_sub_tl + sct_ovh_tl
                        total_ll = sct_mtl_ll + sct_lbr_ll + sct_bdn_ll
                        + sct_sub_ll + sct_ovh_ll
                        mtl_tot  = sct_mtl_tl + sct_mtl_ll
                        lbr_tot  = sct_lbr_tl + sct_lbr_ll
                        bdn_tot  = sct_bdn_tl + sct_bdn_ll
                        ovh_tot  = sct_ovh_tl + sct_ovh_ll
                        sub_tot  = sct_sub_tl + sct_sub_ll.
                  end.
                  else do:
                     assign
                        total_tl = 0
                        total_ll = 0
                        mtl_tot  = 0
                        lbr_tot  = 0
                        bdn_tot  = 0
                        ovh_tot  = 0
                        sub_tot  = 0.
                  end.

                  assign
                     mtl_ext = (mtl_tot * qty_per)
                     lbr_ext = (lbr_tot * qty_per)
                     bdn_ext = (bdn_tot * qty_per)
                     ovh_ext = (ovh_tot * qty_per)
                     sub_ext = (sub_tot * qty_per)
                     scrp_pct = 0.

                  if net_qty <> 0
                  then do:
                     scrp_pct = 100 * (net_qty - qty_per) / net_qty.
                  end.

                  if scrp_pct <> 100
                  then do:
                     assign
                        mtl_ext = mtl_ext * (100 / (100 - scrp_pct))
                        lbr_ext = lbr_ext * (100 / (100 - scrp_pct))
                        bdn_ext = bdn_ext * (100 / (100 - scrp_pct))
                        ovh_ext = ovh_ext * (100 / (100 - scrp_pct))
                        sub_ext = sub_ext * (100 / (100 - scrp_pct)).
                  end.

                  assign
                     total_ext = mtl_ext + lbr_ext
                              + bdn_ext + sub_ext + ovh_ext
                     des[4]    = " "
                     des[5]    = " ".

                  if scrp_pct <> 0 and yield_pct = 100
                  then do:
                     des[4] = "SCRAP" + string(scrp_pct, ">>9.99") + "%".
                  end.
                  if scrp_pct = 0 and yield_pct <> 100
                  then do:
                     des[4] = des[4] + "YIELD" + string(yield_pct) + "%".
                  end.
                  if scrp_pct <> 0 and yield_pct <> 100
                  then do:
                     assign
                        des[4] = "SCRAP" + string(scrp_pct, ">>9.99") + "%"
                        des[5] = "YIELD" + string(yield_pct)      + "%".
                  end.

                  if available sct_det and sct_cst_date <> ?
                  then do:
                     des[3] = " " + string(year(sct_cst_date))
                           + "-" + string(month(sct_cst_date),"99")
                           + "-" + string(day(sct_cst_date),"99").
                  end.

                  if des[2] = " "
                  then do:
                     assign
                        des[2] = des[3]
                        des[3] = " ".
                  end.

                  if des[2] = des[3]
                  then do:
                     des[3] = " ".
                  end.

                  if des[3] = " "
                  then do:
                     assign
                        des[3] = des[4]
                        des[4] = des[5]
                        des[5] = " ".
                  end.

                  des[6] = " ".

                  if bom_code <> ps_mstr.ps_comp
                  then do:
                     des[6] = "BOMCD" + bom_code.
                  end.

                  /*create description for previous tt_ps_mstr*/
                  run AddDescriptions(input-output des_temp_count,
                                       count_comp, des_temp).

                  create tt_ps_mstr.
                  count_comp = count_comp + 1.
                  buffer-copy ps_mstr to tt_ps_mstr no-error.
                  assign
                     tt_ps_mstr.lvl                = lvl
                     tt_ps_mstr.um                 = um
                     tt_ps_mstr.unique_id          = count_comp
                     tt_ps_mstr.ref_unique_id      = 1
                     tt_ps_mstr.id_group_by_parent = parent_id.

                  if batch_qty <> 0 and batch_qty <> 1
                  then do:
                     tt_ps_mstr.batch_qty = batch_qty.
                     tt_ps_mstr.batch_um = batch_um.
                     tt_ps_mstr.display_batch = true.
                  end.

                  for first ptal_mstr
                     where ptal_mstr.ptal_domain = global_domain
                     and ptal_part = ps_mstr.ps_comp
                     and ptal_active no-lock:
                  end.
                  if available ptal_mstr
                  then do:
                     des_temp_count = des_temp_count + 1.
                     des_temp[des_temp_count] = "ALTNB" + ptal_alt_part.
                  end.

                  /* Display first level amounts */
                  des_temp_count = des_temp_count + 1.
                  des_temp[des_temp_count] = des[1].

                  create ttCategoryCost.
                  assign
                     ttCategoryCost.level_label   =
                        getTermLabelRt("THIS_LEVEL",12)
                     ttCategoryCost.tot           = total_tl
                     ttCategoryCost.ref_unique_id = count_comp.

                  if available sct_det
                  then do:
                  assign
                     ttCategoryCost.mtl = sct_mtl_tl
                     ttCategoryCost.lbr = sct_lbr_tl
                     ttCategoryCost.bdn = sct_bdn_tl
                     ttCategoryCost.ovh = sct_ovh_tl
                     ttCategoryCost.sub = sct_sub_tl.
                  end.

                  /*Display second level amounts. */
                  des_temp_count = des_temp_count + 1.
                  des_temp[des_temp_count] = des[2].

                  create ttCategoryCost.
                  assign
                     ttCategoryCost.level_label   =
                        getTermLabelRt("LOWER_LEVEL",12)
                     ttCategoryCost.tot           = total_ll
                     ttCategoryCost.ref_unique_id = count_comp.

                  if available sct_det
                  then do:
                     assign
                        ttCategoryCost.mtl = sct_mtl_ll
                        ttCategoryCost.lbr = sct_lbr_ll
                        ttCategoryCost.bdn = sct_bdn_ll
                        ttCategoryCost.ovh = sct_ovh_ll
                        ttCategoryCost.sub = sct_sub_ll.
                  end.
                  else do:
                     assign
                        ttCategoryCost.mtl = 0
                        ttCategoryCost.lbr = 0
                        ttCategoryCost.bdn = 0
                        ttCategoryCost.ovh = 0
                        ttCategoryCost.sub = 0.
                  end.

                  if des[3] = " "
                  then do:
                     assign
                        des[3] = des[4]
                        des[4] = des[5]
                        des[5] = " ".

                     if des[3] = " "
                     then do:
                        assign
                           des[3] = des[5]
                           des[5] = " ".
                     end.

                     if des[3] = " "
                     then do:
                        assign
                           des[3] = des[6]
                           des[6] = " ".
                     end.
                  end.

                  /* Display totals */
                  des_temp_count = des_temp_count + 1.
                  des_temp[des_temp_count] = des[3].

                  create ttCategoryCost.
                  assign
                     ttCategoryCost.level_label    =
                        getTermLabelRt("UNIT_TOTAL",12)
                     ttCategoryCost.mtl            = mtl_tot
                     ttCategoryCost.lbr            = lbr_tot
                     ttCategoryCost.bdn            = bdn_tot
                     ttCategoryCost.ovh            = ovh_tot
                     ttCategoryCost.sub            = sub_tot
                     ttCategoryCost.ref_unique_id  = count_comp.

                  if available sct_det
                  then do:
                     ttCategoryCost.tot = sct_cst_tot.
                  end.
                  else do:
                     ttCategoryCost.tot = 0.
                  end.

                  if des[4] = " "
                  then do:
                     assign
                        des[4] = des[6]
                        des[6] = " ".
                  end.

                  /* Display extended totals */
                  des_temp_count = des_temp_count + 1.
                  des_temp[des_temp_count] = des[4].

                  create ttCategoryCost.
                  assign
                     ttCategoryCost.level_label    =
                        getTermLabelRt("EXT_TOTAL",12)
                     ttCategoryCost.mtl            = mtl_ext
                     ttCategoryCost.lbr            = lbr_ext
                     ttCategoryCost.bdn            = bdn_ext
                     ttCategoryCost.ovh            = ovh_ext
                     ttCategoryCost.sub            = sub_ext
                     ttCategoryCost.tot            = total_ext
                     ttCategoryCost.ref_unique_id  = count_comp.

                  if des[5] <> " "
                  then do:
                     des_temp_count = des_temp_count + 1.
                     des_temp[des_temp_count] = des[5].
                  end.

                  if des[6] <> " "
                  then do:
                     des_temp_count = des_temp_count + 1.
                     des_temp[des_temp_count] = des[6].
                  end.

                  /* IF THIS ITEM IS LINKED DISPLAY THE GL COST SITE */
                  if l_linked
                  then do:
                     des_temp_count = des_temp_count + 1.
                     des_temp[des_temp_count] = des[8].
                  end.

                  assign
                     joint_type  = ""
                     joint_label = "".

                  for first ptp_det no-lock
                     where ptp_det.ptp_domain = global_domain
                     and ptp_part = ps_mstr.ps_comp
                     and ptp_site = site:
                  end.

                  if available ptp_det
                  then do:
                     joint_type = ptp_joint_type.
                  end.

                  else do:
                     for first pt_mstr1 no-lock
                        where pt_mstr1.pt_domain = global_domain
                        and pt_mstr1.pt_part = ps_mstr.ps_comp:
                     end.
                     if available pt_mstr1
                     then do:
                        joint_type = pt_mstr1.pt_joint_type.
                     end.
                  end.

                  if joint_type <> ""
                  then do:
                     /* Numeric ps_joint_type returns alpha code, label */
                     {{&us_gp}gplngn2a.i &file     = ""wo_mstr""
                        &field    = ""wo_joint_type""
                        &code     = joint_type
                        &mnemonic = joint_code
                        &label    = joint_label}

                     des_temp_count = des_temp_count + 1.
                     des_temp[des_temp_count] = " " + joint_label.
                  end.

                  if (total_tl + total_ll = 0)
                     and available ptmstr
                     and ptmstr.pt_pm_code = "P"
                  then do:
                     for first msg_mstr no-lock
                        where msg_nbr = 55
                        and msg_lang = global_user_lang:
                     end.
                     if available msg_mstr
                     then do:
                        /*display*/
                        tt_ps_mstr.msg_desc=msg_mstr.msg_desc.
                     end.
                  end.
               end. /*for each pswkfl*/

               for first ps_mstr no-lock
                  where recid(ps_mstr) = record[level]:
               end.

               if level < maxlevel or maxlevel = 0
               then do:
                  assign
                     comp = bom_code
                     level = level + 1.
                  for first ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp no-lock:
                  end.
               end.
               else do:
                  find next ps_mstr use-index ps_parcomp
                     where ps_mstr.ps_domain = global_domain
                     and ps_mstr.ps_par = comp no-lock no-error.
               end.

               if available sct_det and sct_part = dingbats
               then do:
                  delete sct_det.
               end.
            end.
            else do:
               find next ps_mstr use-index ps_parcomp
                  where ps_mstr.ps_domain = global_domain
                  and ps_mstr.ps_par = comp no-lock no-error.
            end.
         end. /*end repeat: l_linked = false */
      end. /* IF AVAILABLE bom_mstr */
      hMainQuery:get-next().
   end. /* REPEAT QUERY */

   hMainQuery:query-close().
   /*Main QUery end*/

   /*create description for last tt_ps_mstr*/
   run AddDescriptions(input-output des_temp_count, count_comp, des_temp).

END PROCEDURE. /* PROCEDURE CalculateProductStructureCostByCategory */

